package deformedGrid;

import deformation.Deformation;
import grid.Grid;
import grid.GridFactory;
import grid.GridFactoryListener;
import grid.TrivialGridFactory;

/**
 * the base class for grid deformation it ia implemented by most classes that have to handlewith a grid that changed
 *
 */
public class GridDeformation implements GridFactoryListener{

	final private Grid grid;
	private GridFactory gridFactory;
	private Deformation deformation;

	/**
	 * @param grid grid of the src image
	 */
	public GridDeformation(final Grid grid) {
		this.grid =grid;
		this.gridFactory = new TrivialGridFactory(grid);
		this.gridFactory.addGridFactoryListener(this);
	}

	/**
	 * this methode does nothing it is called if the grid need to be recomputed
	 * it can be overridden
	 */
	public void deformationChanged() {
		/**
		 * override it
		 */
	}
	/**
	 * @return the deformation
	 */
	public Deformation getDeformation() {
		if (deformation== null) {
			return null;
		}
		return deformation;
	}

	/**
	 * @return the grid
	 */
	public Grid getGrid() {
		return gridFactory.generateGrid();
	}

	/**
	 * @return the mGrid
	 */
	public GridFactory getGridFactory() {
		return gridFactory;
	}
	
	
	/**
	 * @return the grid
	 */
	public Grid getOriginalGrid() {
		return grid;
	}

	
	
	@Override
	public void gridChanged(GridFactory gridFactory) {	
		if (this.gridFactory == gridFactory) {
			deformationChanged();
		}else{
			gridFactory.removeGridFactoryListener(this);
		}
		
	}
	
	/**
	 * @param grid
	 * @return true if the grid has changed and need to recomputed, false otherwise
	 * @see grid.GridFactory#gridHasChanged(grid.Grid)
	 */
	public boolean gridHasChanged(Grid grid) {
		return gridFactory.gridHasChanged(grid);
	}

	/**
	 * removes the deformation
	 */
	public void removeDeformation(){
		this.gridFactory.removeGridFactoryListener(this);
		this.gridFactory = new TrivialGridFactory(grid);
		this.gridFactory.addGridFactoryListener(this);
		this.deformation = null;
		deformationChanged();
	}

	/**
	 * @param deformation the new deformation
	 */
	public synchronized void setDeformation(Deformation deformation){
		this.gridFactory.removeGridFactoryListener(this);
		this.gridFactory = deformation.generateMorphingGrid(grid);
		this.gridFactory.addGridFactoryListener(this);
		this.deformation = deformation;
		deformationChanged();
	}
	


}
